/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gameheart.client.logic;

import gameheart.server.ServerCard;
import java.io.*;
import gameheart.server.Direction;
import gameheart.transport.*;
import java.util.Arrays;

/**
 *
 * @author win7
 */
public class ClientAdapter {

    Transporter _transporter;

    public ClientAdapter(Transporter transporter) {
        _transporter = transporter;
    }
    private boolean toiLuot = false;
    /**
     * xu ly yeu cau tu server
     * @param waiting  co cho mot lenh dac biet tu server khong
     * @param commandId ma lenh can cho
     * @throws IOException
     */
    public void processMessage() throws MyException {
        Command command = _transporter.GetCommand(false);
        if (command != null) {
            System.out.println("Get command : " + command.getCommandId());
            dispathCommand(command);
        }
    }

    /**
     * doi mot lenh tu server. cac lenh khac van duoc xu ly. lenh dang doi khong duoc xy ly.
     * @param commandId ma lenh can doi
     * @return leng can doi
     * @throws MyException
     */
    private Command GetCommandSynch(int commandId) throws MyException {
        boolean meetRequiredCommand = false;
        Command command = null;
        while (true) {
            command = _transporter.GetCommand(true);
            if (command.getCommandId() == commandId) {
                return command;
            }
            dispathCommand(command);
        }
    }

    /**
     * doi mot lenh tu server. lenh dang doi va cac lenh khac deu duoc xu ly
     * @param commandId ma lenh can doi
     * @throws MyException
     */
    public void WaitCommandSysn(int commandId) throws MyException {
        boolean meetRequiredCommand = false;
        Command command = null;
        while (!meetRequiredCommand) {
            command = _transporter.GetCommand(true);
            if (command.getCommandId() == commandId) {
                meetRequiredCommand = true;
            }
            dispathCommand(command);
        }
    }

    /**
     * phan phoi lenh den cac ham can thiet.
     * @param command lenh can phan phoi
     */
    private void dispathCommand(Command command) {
        switch (command.getCommandId()) {
            case CommandIds.requestPlayId: {
                toiLuot = true;
                break;
            }
            case CommandIds.requestDrawPlayCardId: {
                String cardNumber = command.getValueOfArg(CommandMessageTag.CardNumberTag);
                String cardType = command.getValueOfArg(CommandMessageTag.CardTypeTag);
                String userIdString = command.getValueOfArg(CommandMessageTag.UserIdTag);
                if (cardNumber != null && cardType != null && userIdString != null) {
                    isHaveDrawMovingCard = true;
                    card = new ServerCard();
                    card.setDiem(Integer.valueOf(cardNumber));
                    card.setType(ServerCard.Type.values()[Integer.valueOf(cardType)]);
                    userId = Integer.valueOf(userIdString);
                }
                break;
            }
            case CommandIds.CurrentUserId: {
                _currentUserId = Integer.parseInt(command.getValueOfArg(CommandMessageTag.UserIdTag));
                break;
            }
            case CommandIds.RoundTripEndId: {
                _roundTripEnd = true;
                _getCardUser = Integer.parseInt(command.getValueOfArg(CommandMessageTag.UserIdTag));
                System.out.println("Dang xu ly lenh roundtrip end");
                break;
            }
            case CommandIds.GameEndId: {
                _gameEnd = true;
                break;
            }
            case CommandIds.DealRequestId: {
                int cardNumber = command.getArgNumber() / 2;
                ServerCard[] cards = new ServerCard[cardNumber];
                for (int index = 0; index < cardNumber; ++index) {
                    cards[index] = new ServerCard();
                    int diem = Integer.parseInt(command.getArgdValues()[index * 2]);
                    ServerCard.Type type = ServerCard.Type.values()[(Integer.parseInt(command.getArgdValues()[index * 2 + 1]))];
                    cards[index].setDiem(diem);
                    cards[index].setType(type);
                }
                Arrays.sort(cards);
                _myCards = cards;
                _haveDealRequest = true;
                break;

            }
            case CommandIds.PassCardRequest: {
                _havePassCardRequest = true;
                String directString = command.getValueOfArg(CommandMessageTag.DirectionTag);
                int directIndex = Integer.parseInt(directString);
                _direct = Direction.values()[directIndex];
                _passCardDone = false;
                break;
            }
            case CommandIds.UseNameOfPlayers: {
                _userNames = command.getArgdValues();
                break;
            }
            case CommandIds.passCardDone: {
                int cardNumber = command.getArgNumber() / 2;
                ServerCard[] cards = new ServerCard[cardNumber];
                for (int index = 0; index < cardNumber; ++index) {
                    cards[index] = new ServerCard();
                    int diem = Integer.parseInt(command.getArgdValues()[index * 2]);
                    ServerCard.Type type = ServerCard.Type.values()[(Integer.parseInt(command.getArgdValues()[index * 2 + 1]))];
                    cards[index].setDiem(diem);
                    cards[index].setType(type);
                }

                Arrays.sort(cards);
                _myCards = cards;
                _passCardDone = true;
                break;
            }
            case CommandIds.userJoinedGame: {
                int userID = Integer.parseInt(command.getValueOfArg(CommandMessageTag.UserIdTag));
                String userName = command.getValueOfArg(CommandMessageTag.UserNameTag);
                _userNames[userID] = userName;
                break;
            }
            case CommandIds.startGame: {
                startGame = true;
                break;
            }
            case CommandIds.MarkInGame: {
                String[] markStrings = command.getValuesOfArg(CommandMessageTag.MarkTag);
                for (int index = 0; index < 4; ++index) {
                    _marks[index] = Integer.parseInt(markStrings[index]);
                }
                break;
            }
            case CommandIds.PointInHand: {
                _pointInHand = Integer.valueOf(command.getValueOfArg(CommandMessageTag.MarkTag));
                break;
            }
            case CommandIds.HandEnd: {
                _handEnd = true;
                _pointInHand = 0;
                toiLuot = false;
                break;
            }
            case CommandIds.Chat: {
                _newestMessageForDisplay = _userNames[Integer.parseInt(command.getValueOfArg(CommandMessageTag.UserIdTag))] +" : " + command.getValueOfArg(CommandMessageTag.MessageTag);
                System.out.println("received message : " + command.getValueOfArg(CommandMessageTag.MessageTag));
                break;
            }
        }
    }
    public void beginNewHand()
    {
        _handEnd = false;
    }
    public void finishDealCard()
    {
        _haveDealRequest = false;
    }
    /**
     * goi thong bao chat
     * @param message
     */
    public void SendChatMessage(String message) throws MyException
    {
        String[] argNames = {CommandMessageTag.MessageTag};
        String[] argValues ={message};
        SendCommand(CommandIds.Chat, argNames, argValues, 1);
    }
    private String _newestMessageForDisplay = "message for me";
    private boolean _handEnd = false;
    boolean startGame = false;

    public boolean IsStartGame() {
        return startGame;
    }

    public void newHand() {
        _handEnd = false;
    }

    /**
     * kiem tra xem toi luot di khong
     * @return true : toi luot di. false : nguoc lai.
     */
    public boolean IsHavePlayRequest() {
        return toiLuot;
    }

    /**
     * client thuc hien nuoc di
     * @param card card client danh
     * @return true : nuoc di hop len. false : nuoc di khong hop le.
     * @throws MyException
     */
    public boolean SendPlayReply(ServerCard card) throws MyException {
        int replyCode = 0;
        int argNumber = 2;
        String[] argNames = new String[argNumber];
        String[] argValues = new String[argNumber];
        argNames[0] = CommandMessageTag.CardNumberTag;
        argValues[0] = String.valueOf(card.getDiem());
        argNames[1] = CommandMessageTag.CardTypeTag;
        argValues[1] = String.valueOf(card.getType().ordinal());
//        Command command = new Command();
//        command.setCommandId( CommandIds.playReplyId);
//        command.setArgNumber(argNumber);
//        command.setArgNames(argNames);
//        command.setArgdValues(argValues);
        System.out.println("Goi card ve server." + String.valueOf(card.getDiem()));
        SendCommand(CommandIds.playReplyId, argNames, argValues, argNumber);
        Command command = GetCommandSynch(CommandIds.PlayResult);
        replyCode = Integer.parseInt(command.getValueOfArg(CommandMessageTag.ResultTag));
        if (replyCode == 1) {
            toiLuot = false;
            return true;
        }
        toiLuot = true;
        return false;

    }
    private int userId;
    private boolean isHaveDrawMovingCard = false;

    /**
     * co nguoi choi vua thuc hien nuoc di (ke ca nguoi choi hien tai)
     * @return true : co nguo choi thuc hien nuoc di. false : khong co.
     */
    public boolean IsHaveDrawMovingCard() {
        return isHaveDrawMovingCard;
    }
    private ServerCard card = null;

    /**
     * client da thuc hien cap nhap man hinh sau khi co nguoi  choi thuc hien nuoc di.
     * @throws MyException
     */
    public void SendDrawedReply() throws MyException {
        SendCommand(CommandIds.drawedReplyId, null, null, 0);
        isHaveDrawMovingCard = false;
    }

    /**
     * userId cua nguoi choi vua thuc hien nuoc di.
     * @return the userId
     */
    public int getPlayedUserId() {
        return userId;
    }

    /**
     * lay quan bai nguoi choi  vua danh
     * @return the card : quan bai nguoi choi vua danh
     */
    public ServerCard getCard() {
        return card;
    }
    int _currentUserId = -1;

    /**
     * lay user id cua nguoi choi hien tai
     * @return user id cua nguoi choi hien tai.
     */
    public int getCurrentUserId() {
        return _currentUserId;
    }
    private int soClient = 4;
    private String[] _userNames = {"", "", "", ""};

    /**
     * lay user name cua nguoi choi co user id
     * @param userId user id cua nguoi choi can lay user name
     * @return user name
     */
    public String getUserName(int userId) {
        return _userNames[userId];
    }

    /**
     * tra ve user name cua 4 nguoi choi
     * neu co vi tri chua co nguoi choi tham gi se tra ve String co do dai bang 0 tai vi tri do
     * @return user names
     */
    public String[] getUserNames() {
        return _userNames;
    }
    private boolean _haveDealRequest = false;

    /**
     * co yeu cau chia bai.
     * @return
     */
    public boolean IsHaveDealRequest() {
        return _haveDealRequest;
    }
    private int soQuanBai = 13;
    private ServerCard[] _myCards = new ServerCard[soQuanBai];

    /**
     * quan bai duoc chia cho nguoi choi hien tai.
     * @return
     */
    public ServerCard[] getMyCards() {
        return _myCards;
    }
    private boolean _roundTripEnd = false;

    /**
     * da het mot vong danh bai chua ( ca 4 nguoi choi deu da danh)
     * @return true : da het.
     */
    public boolean IsRoundTripEnd() {
        return _roundTripEnd;
    }
    public void finishRoundTripDraw()
    {
        _roundTripEnd = false;
    }
    private int _getCardUser = -1;

    /**
     * lay user id cua nguoi choi nhan bai cua vong danh.
     * @return user id
     */
    public int getIdOfGetCardUser() {
        return _getCardUser;
    }
    private boolean _gameEnd = false;

    /**
     *
     * @return
     */
    public boolean IsGameEnd() {
        return _gameEnd;
    }
    int[] _marks = new int[4];

    /**
     * diem cua cac nguoi choi.
     * @return diem cua cac nguoi choi
     */
    public int[] getMarkOfPlayers() {
        return _marks;
    }
    volatile int _pointInHand = 0;

    /**
     * so diem da lay cua nguoi trong hand hien tai
     * @return diem cua cac nguoi choi.
     */
    public int getPointInHand() {
        return _pointInHand;
    }
    private boolean _passCardDone = true;

    public boolean passCardDone() {
        return _passCardDone;
    }

    /**
     * @param card the card to set
     */
//    public void setCard(CardServer card) {
//        this.card = card;
//    }
    public void SendCommand(int commandId, String[] argName, String[] argValue, int argNumber) throws MyException {
        Command command = new Command();
        command.setCommandId(commandId);
        command.setArgNames(argName);
        command.setArgNumber(argNumber);
        command.setArgdValues(argValue);
        _transporter.SendCommand(command);
    }
    private boolean _havePassCardRequest = false;
    private Direction _direct = null;

    public boolean isHavePassCardRequest() {
        return _havePassCardRequest;
    }

    public Direction getPassCardDirection() {
        return _direct;
    }

    public void passCard(ServerCard[] cards) throws MyException {
        int argNumber = 3;
        String[] argNames = new String[argNumber * 2];
        String[] argValues = new String[argNumber * 2];
        for (int index = 0; index < argNumber; ++index) {
            argNames[index * 2] = CommandMessageTag.CardNumberTag;
            argValues[index * 2] = String.valueOf(cards[index].getDiem());
            argNames[index * 2 + 1] = CommandMessageTag.CardTypeTag;
            argValues[index * 2 + 1] = String.valueOf(cards[index].getType().ordinal());
        }
        _havePassCardRequest = false;
        SendCommand(CommandIds.PassCard, argNames, argValues, argNumber * 2);

    }

    /**
     * tham gia game.
     * @param userName user name cua nguoi choi muon tham gia
     * @return true : duoc chap nhan. false : khong duoc chap nhan
     * @throws MyException
     */
    public boolean joinGame(String userName) throws MyException {
        String[] argNames = new String[1];
        String[] argValues = new String[1];
        argNames[0] = CommandMessageTag.UserNameTag;
        argValues[0] = userName;
        SendCommand(CommandIds.JoinGame, argNames, argValues, 1);
        Command command = GetCommandSynch(CommandIds.JoinGameResult);
        boolean result = Boolean.parseBoolean(command.getValueOfArg(CommandMessageTag.JoinGameResultTag));
        return result;
    }

    /**
     * lay user id cua nguoi choi dang co luot di
     * @return user id
     */
    public int getCurrentPlayingUserId() throws MyException {
        SendCommand(CommandIds.UserIdOfPlayingUserRequest, null, null, 0);
        Command command = GetCommandSynch(CommandIds.UserIdOfPlayingUser);
        int userId = Integer.parseInt(command.getValueOfArg(CommandMessageTag.UserIdTag));
        return userId;
    }

    /**
     * @return the _handEnd
     */
    public boolean isHandEnd() {
        return _handEnd;
    }

    /**
     * @return the _newestMessage
     */
    public String getNewestMessage() {
        return _newestMessageForDisplay;
    }
}
